package com.yunquan.ohana.view

import android.annotation.SuppressLint
import android.content.Context
import android.util.AttributeSet
import android.view.MotionEvent
import android.view.View
import android.view.ViewConfiguration
import android.widget.FrameLayout
import androidx.core.content.withStyledAttributes
import androidx.core.view.children
import com.yunquan.ohana.R
import kotlin.math.abs

class SwipeDeleteLayout @JvmOverloads constructor(
    context: Context,
    attrs: AttributeSet? = null,
    defStyleAttr: Int = 0
) : FrameLayout(context, attrs, defStyleAttr) {

    // 状态枚举
    enum class State {
        CLOSED,       // 关闭状态
        OPENING,      // 正在打开
        OPENED,       // 打开状态
        CLOSING,      // 正在关闭
        DRAGGING      // 正在拖动
    }

    // 滑动方向枚举
    enum class SwipeDirection {
        LEFT_TO_RIGHT, // 从左向右滑动（关闭）
        RIGHT_TO_LEFT  // 从右向左滑动（打开）
    }

    // 监听器接口
    interface OnSwipeListener {
        fun onStateChanged(state: State, direction: SwipeDirection?)
        fun onSwipeStart(direction: SwipeDirection)
        fun onSwipeEnd(direction: SwipeDirection, isMenuOpened: Boolean)
        fun onSwipeProgress(progress: Float, direction: SwipeDirection)
    }

    companion object {
        private const val ANIMATION_DURATION = 250L // 动画时长

        @SuppressLint("StaticFieldLeak")
        private var openedMenu: SwipeDeleteLayout? = null // 当前打开的菜单实例

        @JvmStatic
        fun closeAllMenus() {
            openedMenu?.closeMenu(SwipeDirection.LEFT_TO_RIGHT)
            openedMenu = null
        }

        @JvmStatic
        fun getOpenedMenu(): SwipeDeleteLayout? = openedMenu

        @JvmStatic
        fun hasOpenedMenu(): Boolean = openedMenu != null
    }

    // 属性
    private var swipeEnabled = true
    private var closeOnClick = true // 点击内容区域是否关闭菜单
    private var menuWidth = 0 // 菜单宽度
    private var autoCloseOthers = true // 是否自动关闭其他打开的菜单

    // 状态管理
    private var currentState = State.CLOSED
    private var isSwiping = false
    private var lastInterceptX = 0f
    private var lastInterceptY = 0f
    private var lastTouchX = 0f
    private var currentSwipeDirection: SwipeDirection? = null

    // 子视图引用
    private lateinit var contentView: View
    private lateinit var menuView: View

    // 监听器
    private var swipeListener: OnSwipeListener? = null

    // 触摸阈值
    private val touchSlop by lazy {
        ViewConfiguration.get(context).scaledTouchSlop
    }

    init {
        initAttrs(attrs)
    }

    private fun initAttrs(attrs: AttributeSet?) {
        attrs?.let {
            context.withStyledAttributes(it, R.styleable.SwipeDeleteLayout) {
                swipeEnabled = getBoolean(
                    R.styleable.SwipeDeleteLayout_swipeEnabled, true
                )
                closeOnClick = getBoolean(
                    R.styleable.SwipeDeleteLayout_closeOnClick, true
                )
                autoCloseOthers = getBoolean(
                    R.styleable.SwipeDeleteLayout_autoCloseOthers, true
                )
            }
        }
    }

    override fun onFinishInflate() {
        super.onFinishInflate()
        findChildViews()
    }

    override fun onMeasure(widthMeasureSpec: Int, heightMeasureSpec: Int) {
        super.onMeasure(widthMeasureSpec, heightMeasureSpec)
        // 测量后获取菜单的实际宽度
        menuWidth = menuView.measuredWidth
    }

    override fun onLayout(changed: Boolean, left: Int, top: Int, right: Int, bottom: Int) {
        super.onLayout(changed, left, top, right, bottom)
        // 确保菜单初始位置在右侧外部
        menuView.translationX = width.toFloat()
    }

    private fun findChildViews() {
        val children = children.toList()
        if (children.size < 2) {
            throw IllegalStateException("SwipeDeleteLayout must have at least 2 children")
        }

        // 第一个子视图是菜单，第二个是内容
        menuView = children[0]
        contentView = children[1]

        // 设置内容视图点击监听
        contentView.setOnClickListener {
            if (closeOnClick && isOpened()) {
                closeMenu(SwipeDirection.LEFT_TO_RIGHT)
            } else {
                // 如果点击时没有打开菜单，检查是否需要关闭其他菜单
                if (autoCloseOthers && openedMenu != null && openedMenu != this) {
                    openedMenu?.closeMenu(SwipeDirection.LEFT_TO_RIGHT)
                }
            }
        }
    }

    // 处理横向滑动冲突的核心方法
    override fun onInterceptTouchEvent(ev: MotionEvent): Boolean {
        if (!swipeEnabled) return super.onInterceptTouchEvent(ev)

        when (ev.action) {
            MotionEvent.ACTION_DOWN -> {
                lastInterceptX = ev.x
                lastInterceptY = ev.y
                lastTouchX = ev.x
                isSwiping = false
                currentSwipeDirection = null

                // 在按下时检查是否需要关闭其他打开的菜单
                if (autoCloseOthers && openedMenu != null && openedMenu != this) {
                    openedMenu?.closeMenu(SwipeDirection.LEFT_TO_RIGHT)
                }
            }

            MotionEvent.ACTION_MOVE -> {
                val deltaX = ev.x - lastInterceptX
                val deltaY = ev.y - lastInterceptY

                // 检查是否主要是横向滑动
                if (abs(deltaX) > touchSlop && abs(deltaX) > abs(deltaY)) {
                    // 确定滑动方向
                    val direction = if (deltaX > 0) {
                        SwipeDirection.LEFT_TO_RIGHT // 向右滑动
                    } else {
                        SwipeDirection.RIGHT_TO_LEFT // 向左滑动
                    }

                    // 根据当前状态和方向决定是否拦截
                    val shouldIntercept = when {
                        // 向左滑动且当前是关闭状态 - 打开菜单
                        direction == SwipeDirection.RIGHT_TO_LEFT && currentState == State.CLOSED -> true
                        // 向右滑动且当前是打开状态 - 关闭菜单
                        direction == SwipeDirection.LEFT_TO_RIGHT && currentState == State.OPENED -> true
                        // 任何方向的拖动状态都拦截
                        currentState == State.DRAGGING -> true
                        else -> false
                    }

                    if (shouldIntercept) {
                        isSwiping = true
                        currentSwipeDirection = direction
                        parent.requestDisallowInterceptTouchEvent(true)
                        swipeListener?.onSwipeStart(direction)
                        updateState(State.DRAGGING, direction)
                        return true
                    }
                }
            }

            MotionEvent.ACTION_UP, MotionEvent.ACTION_CANCEL -> {
                isSwiping = false
            }
        }

        return super.onInterceptTouchEvent(ev)
    }

    @SuppressLint("ClickableViewAccessibility")
    override fun onTouchEvent(event: MotionEvent): Boolean {
        if (!swipeEnabled) return super.onTouchEvent(event)

        when (event.action) {
            MotionEvent.ACTION_DOWN -> {
                lastTouchX = event.x
                return true
            }

            MotionEvent.ACTION_MOVE -> {
                if (isSwiping && currentSwipeDirection != null) {
                    val deltaX = event.x - lastTouchX
                    lastTouchX = event.x
                    handleSwipeMove(deltaX, currentSwipeDirection!!)
                    return true
                }
            }

            MotionEvent.ACTION_UP, MotionEvent.ACTION_CANCEL -> {
                if (isSwiping && currentSwipeDirection != null) {
                    handleSwipeEnd(currentSwipeDirection!!)
                    isSwiping = false
                    currentSwipeDirection = null
                    return true
                }
            }
        }

        return super.onTouchEvent(event)
    }

    private fun handleSwipeMove(deltaX: Float, direction: SwipeDirection) {
        val currentTranslation = contentView.translationX
        var newTranslationX: Float

        when (direction) {
            SwipeDirection.RIGHT_TO_LEFT -> {
                // 向左滑动：内容向左移动，菜单从右侧进入
                newTranslationX = (currentTranslation + deltaX).coerceAtMost(0f)
                val menuTranslation = width + newTranslationX
                menuView.translationX = menuTranslation.coerceAtLeast(0f)
            }

            SwipeDirection.LEFT_TO_RIGHT -> {
                // 向右滑动：内容向右移动，菜单向右退出
                newTranslationX = (currentTranslation + deltaX).coerceAtLeast(-menuWidth.toFloat())
                val menuTranslation = width + newTranslationX
                menuView.translationX = menuTranslation.coerceAtMost(width.toFloat())
            }
        }

        contentView.translationX = newTranslationX

        // 计算滑动进度 (0f - 1f)
        val progress = abs(newTranslationX) / menuWidth
        swipeListener?.onSwipeProgress(progress.coerceIn(0f, 1f), direction)
    }

    private fun handleSwipeEnd(direction: SwipeDirection) {
        val currentTranslation = contentView.translationX
        val isMenuOpened: Boolean

        when (direction) {
            SwipeDirection.RIGHT_TO_LEFT -> {
                // 向左滑动结束：如果滑动距离超过菜单宽度的一半则打开，否则关闭
                isMenuOpened = abs(currentTranslation) > menuWidth / 2f
                if (isMenuOpened) {
                    openMenu(direction)
                } else {
                    closeMenu(direction)
                }
            }

            SwipeDirection.LEFT_TO_RIGHT -> {
                // 向右滑动结束：如果滑动距离超过菜单宽度的一半则关闭，否则保持打开
                isMenuOpened = abs(currentTranslation) < menuWidth / 2f
                if (isMenuOpened) {
                    openMenu(direction)
                } else {
                    closeMenu(direction)
                }
            }
        }

        swipeListener?.onSwipeEnd(direction, isMenuOpened)
    }

    // 公开方法
    fun openMenu(direction: SwipeDirection = SwipeDirection.RIGHT_TO_LEFT) {
        if (!swipeEnabled) return

        // 打开前先关闭其他已打开的菜单
        if (autoCloseOthers && openedMenu != null && openedMenu != this) {
            openedMenu?.closeMenu(SwipeDirection.LEFT_TO_RIGHT)
        }

        contentView.animate()
            .translationX(-menuWidth.toFloat())
            .setDuration(ANIMATION_DURATION)
            .withStartAction { updateState(State.OPENING, direction) }
            .withEndAction {
                updateState(State.OPENED, direction)
                openedMenu = this // 记录当前打开的菜单
            }
            .start()

        menuView.animate()
            .translationX((width - menuWidth).toFloat())
            .setDuration(ANIMATION_DURATION)
            .start()
    }

    fun closeMenu(direction: SwipeDirection = SwipeDirection.LEFT_TO_RIGHT) {
        contentView.animate()
            .translationX(0f)
            .setDuration(ANIMATION_DURATION)
            .withStartAction { updateState(State.CLOSING, direction) }
            .withEndAction {
                updateState(State.CLOSED, direction)
                // 如果关闭的是当前记录的菜单，清空记录
                if (openedMenu == this) {
                    openedMenu = null
                }
            }
            .start()

        menuView.animate()
            .translationX(width.toFloat())
            .setDuration(ANIMATION_DURATION)
            .start()
    }

    private fun updateState(newState: State, direction: SwipeDirection? = null) {
        if (newState != currentState) {
            currentState = newState
            swipeListener?.onStateChanged(newState, direction)
        }
    }

    fun isOpened(): Boolean = currentState == State.OPENED

    fun getMenuWidth(): Int = menuWidth

    fun setSwipeEnabled(enabled: Boolean) {
        swipeEnabled = enabled
        if (!enabled && isOpened()) {
            closeMenu(SwipeDirection.LEFT_TO_RIGHT)
        }
    }

    fun setCloseOnClick(close: Boolean) {
        closeOnClick = close
    }

    fun setAutoCloseOthers(autoClose: Boolean) {
        autoCloseOthers = autoClose
    }

    fun setOnSwipeListener(listener: OnSwipeListener) {
        swipeListener = listener
    }

    // 关闭所有打开的菜单
    fun closeAllOpenedMenus() {
        if (isOpened()) {
            closeMenu(SwipeDirection.LEFT_TO_RIGHT)
        }
        openedMenu?.closeMenu(SwipeDirection.LEFT_TO_RIGHT)
        openedMenu = null
    }

    // 手动设置菜单宽度（如果需要动态调整）
    fun setMenuWidth(width: Int) {
        menuWidth = width
        if (isOpened()) {
            // 如果当前是打开状态，重新调整位置
            contentView.translationX = -menuWidth.toFloat()
            menuView.translationX = (this.width - menuWidth).toFloat()
        }
    }
}